/*
*    Qizx/open 3.0 beta
*
* This code is the open-source version of Qizx.
* Copyright (C) 2004-2009 Axyana Software -- All rights reserved.
*
* The contents of this file are subject to the Mozilla Public License 
*  Version 1.1 (the "License"); you may not use this file except in 
*  compliance with the License. You may obtain a copy of the License at
*  http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
*  WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
*  for the specific language governing rights and limitations under the
*  License.
*
* The Initial Developer of the Original Code is Xavier Franc - Axyana Software.
*
*/
using System;
using Scorer = System.Qizx.Api.FullText.Scorer;
namespace System.Qizx.Queries.Iterators
{
	
	/// <summary> Implements "not in".</summary>
	public class MildNotIterator:BinaryIterator
	{
		public MildNotIterator(PostingIterator what, PostingIterator enclosing):base(what, enclosing)
		{
		}
		
		public override PostingIterator bornAgain()
		{
			return copyFilters(new MildNotIterator(it1.bornAgain(), it2.bornAgain()));
		}
		
		protected internal override bool basicSkipToNode(int nodeId, int limit)
		{
			for (; ; )
			{
				if (!it1.skipToNode(nodeId, limit))
					return noMoreNodes();
				if (!findIntersection())
				{
					getValues(it1);
					return true;
				}
				nodeId = it1.NodeId + 1;
			}
		}
		
		public override bool inRange(int rangeStart, int rangeEnd)
		{
			if (it1.inRange(rangeStart, rangeEnd) && !findIntersection())
				return true;
			return nextBefore(rangeEnd);
		}
		
		public override bool nextBefore(int rangeEnd)
		{
			for (; ; )
			{
				if (it1.NodeId >= rangeEnd || !it1.nextBefore(rangeEnd))
					return noMoreNodes();
				if (!findIntersection())
				{
					getValues(it1);
					return true;
				}
			}
		}
		
		// tries to find an intersection of it1 & it2 
		private bool findIntersection()
		{
			if (!it2.skipToEnclosing(it1.NodeId))
			// TODO huh? correct?
				return false;
			return it1.NodeId <= it2.NodeEnd && it2.NodeId <= it1.NodeEnd;
		}
		
		public override float computeWeighting(Scorer scorer)
		{
			weightNorm = it1.computeWeighting(scorer);
			return weight;
		}
		
		public override float computeScore(Scorer scorer)
		{
			return weight * weightNorm * it1.computeScore(scorer);
		}
	}
}